using System.Collections.Generic;
using System.Linq;

namespace muduoDotNet
{
    /// <summary>
    /// TimerQueue类，用于管理定时器队列
    /// </summary>
    public class TimerQueue : IDisposable
    {
        private readonly EventLoop _loop;
        private readonly SortedList<TimeStamp, List<TimerId>> _timers;
        private readonly Dictionary<TimerId, Timer> _activeTimers;
        private bool _disposed;

        public TimerQueue(EventLoop loop)
        {
            _loop = loop ?? throw new ArgumentNullException(nameof(loop));
            _timers = new SortedList<TimeStamp, List<TimerId>>();
            _activeTimers = new Dictionary<TimerId, Timer>();
            _disposed = false;
        }

        /// <summary>
        /// 添加定时器
        /// </summary>
        /// <param name="callback">定时器回调</param>
        /// <param name="delaySeconds">延迟秒数</param>
        /// <param name="intervalSeconds">间隔秒数，0表示一次性定时器</param>
        /// <returns>TimerId对象</returns>
        public TimerId AddTimer(Action callback, double delaySeconds, double intervalSeconds = 0.0)
        {
            _loop.AssertInLoopThread();
            
            var now = TimeStamp.Now();
            var expiration = now.AddSeconds(delaySeconds);
            
            var timer = new Timer(callback, expiration, intervalSeconds);
            
            // 添加到定时器队列
            if (!_timers.TryGetValue(timer.Expiration, out var timerIds))
            {
                timerIds = new List<TimerId>();
                _timers.Add(timer.Expiration, timerIds);
            }
            
            var timerId = new TimerId(timer, timer.Sequence);
            timerIds.Add(timerId);
            _activeTimers[timerId] = timer;
            
            return timerId;
        }

        /// <summary>
        /// 取消定时器
        /// </summary>
        /// <param name="timerId">要取消的TimerId</param>
        public void Cancel(TimerId timerId)
        {
            _loop.RunInLoop(() =>
            {
                CancelInLoop(timerId);
            });
        }

        /// <summary>
        /// 在事件循环线程中取消定时器
        /// </summary>
        /// <param name="timerId">要取消的TimerId</param>
        private void CancelInLoop(TimerId timerId)
        {
            _loop.AssertInLoopThread();
            
            if (_activeTimers.TryGetValue(timerId, out var timer))
            {
                // 从定时器队列中移除
                if (_timers.TryGetValue(timer.Expiration, out var timerIds))
                {
                    timerIds.Remove(timerId);
                    if (timerIds.Count == 0)
                    {
                        _timers.Remove(timer.Expiration);
                    }
                }
                
                _activeTimers.Remove(timerId);
                timer.Dispose();
            }
        }

        /// <summary>
        /// 获得所有已过期的定时器
        /// </summary>
        /// <param name="now">当前时间</param>
        /// <returns>过期的定时器列表</returns>
        public List<Timer> GetExpiredTimers(TimeStamp now)
        {
            _loop.AssertInLoopThread();
            
            var expired = new List<Timer>();
            var invalidTimerIds = new List<Tuple<TimeStamp, TimerId>>();
            
            // 查找所有已过期的定时器
            foreach (var kv in _timers)
            {
                if (kv.Key > now)
                {
                    break;
                }
                
                foreach (var timerId in kv.Value)
                {
                    if (_activeTimers.TryGetValue(timerId, out var timer))
                    {
                        expired.Add(timer);
                        invalidTimerIds.Add(new Tuple<TimeStamp, TimerId>(kv.Key, timerId));
                    }
                }
            }
            
            // 移除已过期的定时器
            foreach (var item in invalidTimerIds)
            {
                var timerIds = _timers[item.Item1];
                timerIds.Remove(item.Item2);
                if (timerIds.Count == 0)
                {
                    _timers.Remove(item.Item1);
                }
                
                _activeTimers.Remove(item.Item2);
            }
            
            // 重新添加重复的定时器
            foreach (var timer in expired)
            {
                if (timer.Repeat)
                {
                    timer.Restart(now);
                    
                    if (!_timers.TryGetValue(timer.Expiration, out var timerIds))
                    {
                        timerIds = new List<TimerId>();
                        _timers.Add(timer.Expiration, timerIds);
                    }
                    
                    var timerId = new TimerId(timer, timer.Sequence);
                    timerIds.Add(timerId);
                    _activeTimers[timerId] = timer;
                }
                else
                {
                    timer.Dispose();
                }
            }
            
            return expired;
        }

        /// <summary>
        /// 获取最近的定时器的到期时间
        /// </summary>
        /// <returns>最近的定时器的到期时间</returns>
        public TimeStamp GetNearestExpiration()
        {
            _loop.AssertInLoopThread();
            
            if (_timers.Count == 0)
            {
                return TimeStamp.Invalid;
            }
            
            return _timers.First().Key;
        }

        public void Dispose()
        {
            if (!_disposed)
            {
                _disposed = true;
                
                // 清理所有定时器
                foreach (var timer in _activeTimers.Values)
                {
                    timer.Dispose();
                }
                
                _timers.Clear();
                _activeTimers.Clear();
            }
        }
    }
}